package controllers;

import java.util.ArrayList;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import com.google.appengine.api.NamespaceManager;
import models.Residence;
import models.Subscriber;
import models.User;
import play.Logger;
import play.Play;
import play.mvc.Scope.Session;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import utils.constants.SessionConstants;
import utils.passwd.PasswdUtils;

public class Security extends Secure.Security {
	
	public static final String ROOT_ROLE = "ROOT_ROLE";
	// SPECIFIC APPLICATION ROLES
	public static final String ADMIN_ROLE = "ADMIN_ROLE";
	public static final String USER_ROLE = "USER_ROLE";
	public static final String INTERNED_ROLE = "INTERNED_ROLE";
	public static final String FAMILIAR_ROLE = "FAMILIAR_ROLE";
	
	static boolean authenticate(String username, String password) { // TODO implement this method!!!!
		// First check if the user is accessing to a residence
		User user = getCurrentUser(username);
		if(user != null && password != null && !("").equals(password)) {
			try {
				String encodedPassword = PasswdUtils.encodePassword(password);
				return encodedPassword.equals(user.password);
			} catch(Exception e) {
				Logger.error(e, "Error decoding user's password. User: %s and pass: %s", username, password);
			}
		}
		return false;
	}
	
	
	static boolean check(String role) {
    	try {
    		if(Security.ROOT_ROLE.equals(role)) { // The root user is not on BD.
    			String username = Session.current().get(SessionConstants.USER);
    			String confUser = Play.configuration.getProperty("batzen.username", "root");
    			if(confUser.equals(username)) {
    				return true;
    			}
    		} else {
    			User user = getCurrentUser(Session.current().get(SessionConstants.USER));
    			Logger.debug("Checking role: %s for user: %s", role, user != null ? user.username : "Unknown!!!");
    			if(user != null) {
    				if(Security.USER_ROLE.equals(role)) return true;
    				return user.securityRoles.contains(role);
    			}
    		}
    	} catch(Exception e) {
    		Logger.error(e.getMessage());
    		return false;
    	}
        return false;
    }
	
	static User getCurrentUser(String username) {
		if(username == null) return null;
		User user = null;
		if(username.contains("@")) {
			String oldNamespace = NamespaceManager.get();
			String subscriberName = username.substring(username.indexOf("@")+1);
			Subscriber subscriber = Subscriber.findByName(subscriberName);
			if(null==subscriber) return null;
			username = username.substring(0, username.indexOf("@"));
			flash.put("residence", subscriber.name);
			flash.put("usernameV", username);
			NamespaceManager.set(subscriber.name);
			user = User.findByUsername(username);
			NamespaceManager.set(oldNamespace);
		} else {
			if(Play.configuration.getProperty("batzen.username", "root").equals(username)) {
				user = new User();
				user.username =  Play.configuration.getProperty("batzen.username", "root");
				user.password = Play.configuration.getProperty("batzen.password", "7af34762e3acde5ebb77e1ea37bc4be69cb3ba660b3637e3fb3aa84fb0ce36f9fd51880bdc5c455b9b63221d671ce0ed4726542713d658ce8b43e9b77bd2d2ca");
				return user;
			}
		}
		return user;
	}
	
	static void onDisconnect() {
		String connectedUser = connected();
		if(connectedUser==null) return;
		if(connectedUser.contains("@")) {
			flash.success("secure.logout");
			flash.put("domain", connectedUser.substring(connectedUser.indexOf("@")+1));
		}
    }
	
	static void onDisconnected() {
		if(flash.get("domain")!=null) {
			try {
				Application.login(flash.get("domain"));
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}